﻿#region Copyright RenGuiYou. All rights reserved.

//=====================================================
// NeatlyFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================

#endregion

using System;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;

namespace Neatly.UI
{
    [ExecuteInEditMode]
    [DisallowMultipleComponent]
    public class NButtonBase : NUIBehaviour
    {
        protected enum SelectionState
        {
            Normal,
            Pressed,
            Disabled
        }

        public enum Transition
        {
            None,
            ColorTint,
            Sprite,
        }

        [SerializeField]
        protected ColorCombine m_Colors = ColorCombine.DefaultColorCombineBlock;

        protected string normalSpriteName;
        [SerializeField]
        protected string pressedSpriteName;
        [SerializeField]
        protected string disableSpriteName;

        [FormerlySerializedAs("transition")]
        [SerializeField]
        protected Transition m_Transition = Transition.None;
        protected SelectionState m_CurrentSelectionState;

        [SerializeField]
        protected bool m_Interactable = true;

        [SerializeField]
        protected bool m_SoundEnable = true;
        [SerializeField]
        protected string m_SoundName = string.Empty;

        public Graphic targetGraphic
        {
            get { return m_TargetGraphic; }
            set
            {
                if (SetPropertyUtility.SetClass(ref m_TargetGraphic, value)) OnSetProperty();
            }
        }

        [SerializeField]
        protected Graphic m_TargetGraphic;

        [SerializeField]
        protected bool m_ScaleTween = true;

        [SerializeField]
        protected Graphic[] m_OffGraphics;

        protected Vector3 m_SrcScale = Vector3.one;

        public KeyCode virtualKeyCode;


        protected override void Awake()
        {
            if (m_TargetGraphic == null)
            {
                m_TargetGraphic = GetComponent<Graphic>();
            }
            m_SrcScale = transform.localScale;
            var img = m_TargetGraphic as NImage;
            if (img)
            {
                normalSpriteName = img.GetSpriteName();
            }
        }

#if UNITY_EDITOR
        protected override void OnValidate()
        {
            base.OnValidate();
            OnSetProperty(true);
        }
#endif

        protected override void OnEnable()
        {
            base.OnEnable();
            m_CurrentSelectionState = SelectionState.Normal;
            OnSetProperty(true);
            if (m_ScaleTween)
            {
                transform.localScale = m_SrcScale;
            }
        }

        protected bool IsInteractable()
        {
            return m_Interactable;
        }

        protected void OnSetProperty(bool instant = false)
        {
            if (IsInteractable())
            {
                if (m_CurrentSelectionState == SelectionState.Disabled)
                {
                    m_CurrentSelectionState = SelectionState.Normal;
                }
            }
            else
            {
                m_CurrentSelectionState = SelectionState.Disabled;
            }

            DoStateTransition(instant);
        }

        private void DoStateTransition(bool instant)
        {
            if (!gameObject.activeInHierarchy) return;
            Color tintColor;
            string currentSpriteName = "";
            switch (m_CurrentSelectionState)
            {
                case SelectionState.Normal:
                    tintColor = m_Colors.normalColor;
                    currentSpriteName = normalSpriteName;
                    break;
                case SelectionState.Pressed:
                    tintColor = m_Colors.pressedColor;
                    currentSpriteName = pressedSpriteName;
                    break;
                case SelectionState.Disabled:
                    tintColor = NeatlyUI.ButtonDisabledColor;
                    currentSpriteName = disableSpriteName;
                    break;
                default:
                    tintColor = Color.black;
                    break;
            }

            switch (m_Transition)
            {
                case Transition.None:
                    if (m_CurrentSelectionState != SelectionState.Pressed)
                        SetRenderColorGroup(tintColor);
                    break;
                case Transition.ColorTint:
                    StartColorTween(tintColor, instant);
                    break;
                case Transition.Sprite:
                    ChangeSpriteName(currentSpriteName);
                    break;
                
                    
            }
        }

        public void SetTransition(Transition transition)
        {
            m_Transition = transition;
        }

        public void SetRenderColorGroup(Color targetColor)
        {
            SetRenderColor(targetColor);
            if (m_OffGraphics != null)
            {
                for (int i = 0; i < m_OffGraphics.Length; i++)
                {
                    if (m_OffGraphics[i])
                    {
                        m_OffGraphics[i].canvasRenderer.SetColor(targetColor);
                    }
                }
            }
        }

        protected void SetRenderColor(Color targetColor)
        {
            if (m_TargetGraphic == null) return;
            m_TargetGraphic.canvasRenderer.SetColor(targetColor);
        }

        protected void StartColorTween(Color targetColor, bool instant)
        {
            if (instant)
            {
                SetRenderColorGroup(targetColor);
            }
            else
            {
                if (Application.isPlaying)
                {
                    UITween.ButtonPress(this, m_TargetGraphic.canvasRenderer.GetColor(), targetColor, NeatlyUI.ButtonTweenTime);
                }
            }
        }

        public void SetInteractable(bool value)
        {
            if (SetPropertyUtility.SetStruct(ref m_Interactable, value))
            {
                OnSetProperty(true);
            }
        }

        private void ChangeSpriteName(string spriteName)
        {
            if (string.IsNullOrEmpty(spriteName))
            {
                return;
            }
            var img = m_TargetGraphic as NImage;
            if (img != null)
            {
                img.SetSpriteName(spriteName);
            }
        }

        public void SetSpriteName(string spriteName)
        {
            normalSpriteName = spriteName;
            var img = m_TargetGraphic as NImage;
            if (img != null)
            {
                img.SetSpriteName(spriteName);
            }
        }
        
        public void SetPressedSpriteName(string spriteName)
        {
            pressedSpriteName = spriteName;
        }

        public void SetDisableSpriteName(string spriteName)
        {
            disableSpriteName = spriteName;
        }

        public void SetColor(Color color)
        {
            var img = m_TargetGraphic as NImage;
            if (img == null) return;
            img.SetColor(color);
        }

        public void SetColor(float r, float g, float b, float a)
        {
            var img = m_TargetGraphic as NImage;
            if (img == null) return;
            img.SetColor(r, g, b, a);
        }

        public void SetOffColor(bool value = true)
        {
            SetRenderColorGroup(value ? m_Colors.offColor : m_Colors.normalColor);
        }

        public void SetSrcScale(float x, float y, float z)
        {
            Vector3 scale = new Vector3(x, y, z);
            transform.localScale = scale;
            m_SrcScale = scale;
        }
    }
}